#ifndef GY_39_H
#define GY_39_H

#include "sysTick.h"
#include <stm32f4xx.h>

// 模式
#define GY_39_HARDWARE 0
#define GY_39_SOFTWARE 1
#define GY_39_MODE GY_39_HARDWARE

// ACK
#define GY_39_ACK 1         // 使能ACK
#define GY_39_NACK 0        // 禁止ACK
#define GY_39_Sleep 20      // 休眠时间
#define GY_39_Timeout 10000 // 超时时间

// GY39
#define GY_39_ID 0xb6      // I2C从机
#define GY_39_HOST_ID 0x68 // I2C主机

// GY39引脚
#define GY_39_SCL GPIO_Pin_8 // SCL
#define GY_39_SDA GPIO_Pin_9 // SDA

// I2C引脚
#define GY_39_I2C_SCL GPIO_PinSource8 // SCL
#define GY_39_I2C_SDA GPIO_PinSource9 // SDA

// GPIO
#define GY_39_GPIO GPIOB                                                                 // GPIOB组
#define GY_39_GPIO_Pin (GY_39_SCL | GY_39_SDA)                                           // GY_39脚
#define GY_39_RCC_APBPeriphClockCmd RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE)  // APB时钟
#define GY_39_RCC_AHBPeriphClockCmd RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE) // AHB时钟

// I2C
#define GY_39_I2C I2C1                 // I2C1
#define GY_39_I2C_ClockSpeed 100000    // 100k
#define GY_39_GPIO_AF_I2C GPIO_AF_I2C1 // 复用I2C

// 输入模式
#define GY_39_SDA_IN()                               \
    {                                                \
        GPIOB->MODER &= ~(3 << (GY_39_I2C_SDA * 2)); \
        GPIOB->MODER |= 0 << (GY_39_I2C_SDA * 2);    \
    }

// 输出模式
#define GY_39_SDA_OUT()                              \
    {                                                \
        GPIOB->MODER &= ~(3 << (GY_39_I2C_SDA * 2)); \
        GPIOB->MODER |= 1 << (GY_39_I2C_SDA * 2);    \
    }

// SCL
#define GY_39_SCL_Clr() GPIO_ResetBits(GY_39_GPIO, GY_39_SCL) // 置低
#define GY_39_SCL_Set() GPIO_SetBits(GY_39_GPIO, GY_39_SCL)   // 置高

// SDA
#define GY_39_SDA_Clr() GPIO_ResetBits(GY_39_GPIO, GY_39_SDA) // 置低
#define GY_39_SDA_Set() GPIO_SetBits(GY_39_GPIO, GY_39_SDA)   // 置高

// 读SDA
#define GY_39_SDA_READ() GPIO_ReadInputDataBit(GY_39_GPIO, GY_39_SDA) // 读SDA

#pragma pack(1)
typedef struct tagGY_39_ENV {
    uint32_t Lux; // 照度(Lux/100; 单位: lux)
    uint16_t Tem; // 温度(Tem/100; 单位: °C)
    uint32_t Atm; // 气压(Atm/100; 单位: pa)
    uint16_t Hum; // 湿度(Hum/100; 单位: %)
    uint16_t Alt; // 海拔(Alt; 单位: m)
} GY_39_ENV, *PGY_39_ENV;
#pragma pack()

/**
 * @name gy-39初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void gy39_init(void);

/**
 * @name 接收数据
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
GY_39_ENV gy39_recv(void);

/**
 * @name 发送数据
 * @description
 * @function
 * @param {uint8_t} ch 数据
 * @param {uint8_t} addr 地址
 * @returns {void}
 * @requires [ch,addr]
 */
void gy39_send(const uint8_t ch, const uint8_t addr);
#endif
